<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">

  <link rel="apple-touch-icon" type="image/png" href="https://cpwebassets.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png" />
  <meta name="apple-mobile-web-app-title" content="CodePen">

  <link rel="shortcut icon" type="image/x-icon" href="https://cpwebassets.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico" />

  <link rel="mask-icon" type="image/x-icon" href="https://cpwebassets.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg" color="#111" />


  <title>CodePen - React Slider w/ Hover Effect</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">



  <style>
    @import url("https://fonts.googleapis.com/css?family=Playfair+Display:700|IBM+Plex+Sans:500&display=swap");
    :root {
      --color-primary: #6B7A8F;
      --color-secondary: #101118;
      --color-accent: #1D1F2F;
      --color-focus: #6D64F7;
      --base-duration: 600ms;
      --base-ease: cubic-bezier(0.25, 0.46, 0.45, 0.84);
    }

    *, *:before, *:after {
      box-sizing: border-box;
    }

    html, body {
      height: 100%;
    }

    body {
      font-family: "IBM Plex Sans", sans-serif;
      background-color: var(--color-secondary);
    }

    #app {
      align-items: center;
      display: flex;
      height: 100%;
      justify-content: center;
      overflow-x: hidden;
      width: 100%;
    }

    h1, h2, h3 {
      font-family: "Playfair Display", serif;
    }

    .visuallyhidden {
      clip: rect(1px, 1px, 1px, 1px);
      height: 1px;
      overflow: hidden;
      position: absolute !important;
      white-space: nowrap;
      width: 1px;
    }

    .icon {
      fill: var(--color-primary);
      width: 100%;
    }

    .btn {
      background-color: var(--color-primary);
      border: none;
      border-radius: 0.125rem;
      color: white;
      cursor: pointer;
      font-family: inherit;
      font-size: inherit;
      padding: 1rem 2.5rem 1.125rem;
    }
    .btn:focus {
      outline-color: var(--color-focus);
      outline-offset: 2px;
      outline-style: solid;
      outline-width: 3px;
    }
    .btn:active {
      transform: translateY(1px);
    }

    .slider__controls {
      display: flex;
      justify-content: center;
      position: absolute;
      top: calc(100% + 1rem);
      width: 100%;
    }
    .slider__controls .btn {
      --size: 3rem;
      align-items: center;
      background-color: transparent;
      border: 3px solid transparent;
      border-radius: 100%;
      display: flex;
      height: var(--size);
      padding: 0;
      width: var(--size);
    }
    .slider__controls .btn:focus {
      border-color: var(--color-focus);
      outline: none;
    }
    .slider__controls .btn--previous > * {
      transform: rotate(180deg);
    }

    .slider {
      --slide-size: 70vmin;
      --slide-margin: 4vmin;
      height: var(--slide-size);
      margin: 0 auto;
      position: relative;
      width: var(--slide-size);
    }

    .slider__wrapper {
      display: flex;
      margin: 0 calc(var(--slide-margin) * -1);
      position: absolute;
      transition: transform var(--base-duration) cubic-bezier(0.25, 1, 0.35, 1);
    }

    .slide {
      align-items: center;
      color: white;
      display: flex;
      flex: 1;
      flex-direction: column;
      height: var(--slide-size);
      justify-content: center;
      margin: 0 var(--slide-margin);
      opacity: 0.25;
      position: relative;
      text-align: center;
      transition: opacity calc(var(--base-duration) / 2) var(--base-ease), transform calc(var(--base-duration) / 2) var(--base-ease);
      width: var(--slide-size);
      z-index: 1;
    }
    .slide--previous:hover, .slide--next:hover {
      opacity: 0.5;
    }
    .slide--previous {
      cursor: w-resize;
    }
    .slide--previous:hover {
      transform: translateX(2%);
    }
    .slide--next {
      cursor: e-resize;
    }
    .slide--next:hover {
      transform: translateX(-2%);
    }

    .slide--current {
      --x: 0;
      --y: 0;
      --d: 50;
      opacity: 1;
      pointer-events: auto;
      -webkit-user-select: auto;
      -moz-user-select: auto;
      -ms-user-select: auto;
      user-select: auto;
    }
    @media (hover: hover) {
      .slide--current:hover .slide__image-wrapper {
        transform: scale(1.025) translate(calc(var(--x) / var(--d) * 1px), calc(var(--y) / var(--d) * 1px));
      }
    }

    .slide__image-wrapper {
      background-color: var(--color-accent);
      border-radius: 1%;
      height: 100%;
      left: 0%;
      overflow: hidden;
      position: absolute;
      top: 0%;
      transition: transform calc(var(--base-duration) / 4) var(--base-ease);
      width: 100%;
    }

    .slide__image {
      --d: 20;
      height: 110%;
      left: -5%;
      -o-object-fit: cover;
      object-fit: cover;
      opacity: 0;
      pointer-events: none;
      position: absolute;
      top: -5%;
      transition: opacity var(--base-duration) var(--base-ease), transform var(--base-duration) var(--base-ease);
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
      width: 110%;
    }
    @media (hover: hover) {
      .slide--current .slide__image {
        transform: translate(calc(var(--x) / var(--d) * 1px), calc(var(--y) / var(--d) * 1px));
      }
    }

    .slide__headline {
      font-size: 8vmin;
      font-weight: 600;
      position: relative;
    }

    .slide__content {
      --d: 60;
      opacity: 0;
      padding: 4vmin;
      position: relative;
      transition: transform var(--base-duration) var(--base-ease);
      visibility: hidden;
    }
    .slide--current .slide__content {
      -webkit-animation: fade-in calc(var(--base-duration) / 2) var(--base-ease) forwards;
      animation: fade-in calc(var(--base-duration) / 2) var(--base-ease) forwards;
      visibility: visible;
    }
    @media (hover: hover) {
      .slide--current .slide__content {
        transform: translate(calc(var(--x) / var(--d) * -1px), calc(var(--y) / var(--d) * -1px));
      }
    }
    .slide__content > * + * {
      margin-top: 2rem;
    }

    @-webkit-keyframes fade-in {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }

    @keyframes fade-in {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
  </style>

  <script>
    window.console = window.console || function(t) {};
  </script>



  <script>
    if (document.location.search.match(/type=embed/gi)) {
      window.parent.postMessage("resize", "*");
    }
  </script>


</head>

<body translate="no" >
<div id="app"></div>
<script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-1b93190375e9ccc259df3a57c1abc0e64599724ae30d7ea4c6877eb615f89387.js"></script>

<script src='https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/4.2.1/react-transition-group.min.js'></script>
<script id="rendered-js" >
  const slideData = [
    {
      index: 0,
      headline: 'New Fashion Apparel',
      button: 'Shop now',
      src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/225363/fashion.jpg' },

    {
      index: 1,
      headline: 'In The Wilderness',
      button: 'Book travel',
      src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/225363/forest.jpg' },

    {
      index: 2,
      headline: 'For Your Current Mood',
      button: 'Listen',
      src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/225363/guitar.jpg' },

    {
      index: 3,
      headline: 'Focus On The Writing',
      button: 'Get Focused',
      src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/225363/typewriter.jpg' }];




  // =========================
  // Slide
  // =========================

  class Slide extends React.Component {
    constructor(props) {
      super(props);

      this.handleMouseMove = this.handleMouseMove.bind(this);
      this.handleMouseLeave = this.handleMouseLeave.bind(this);
      this.handleSlideClick = this.handleSlideClick.bind(this);
      this.imageLoaded = this.imageLoaded.bind(this);
      this.slide = React.createRef();
    }

    handleMouseMove(event) {
      const el = this.slide.current;
      const r = el.getBoundingClientRect();

      el.style.setProperty('--x', event.clientX - (r.left + Math.floor(r.width / 2)));
      el.style.setProperty('--y', event.clientY - (r.top + Math.floor(r.height / 2)));
    }

    handleMouseLeave(event) {
      this.slide.current.style.setProperty('--x', 0);
      this.slide.current.style.setProperty('--y', 0);
    }

    handleSlideClick(event) {
      this.props.handleSlideClick(this.props.slide.index);
    }

    imageLoaded(event) {
      event.target.style.opacity = 1;
    }

    render() {
      const { src, button, headline, index } = this.props.slide;
      const current = this.props.current;
      let classNames = 'slide';

      if (current === index) classNames += ' slide--current';else
      if (current - 1 === index) classNames += ' slide--previous';else
      if (current + 1 === index) classNames += ' slide--next';

      return /*#__PURE__*/(
              React.createElement("li", {
                        ref: this.slide,
                        className: classNames,
                        onClick: this.handleSlideClick,
                        onMouseMove: this.handleMouseMove,
                        onMouseLeave: this.handleMouseLeave }, /*#__PURE__*/

                      React.createElement("div", { className: "slide__image-wrapper" }, /*#__PURE__*/
                              React.createElement("img", {
                                className: "slide__image",
                                alt: headline,
                                src: src,
                                onLoad: this.imageLoaded })), /*#__PURE__*/



                      React.createElement("article", { className: "slide__content" }, /*#__PURE__*/
                              React.createElement("h2", { className: "slide__headline" }, headline), /*#__PURE__*/
                              React.createElement("button", { className: "slide__action btn" }, button))));



    }}



  // =========================
  // Slider control
  // =========================

  const SliderControl = ({ type, title, handleClick }) => {
    return /*#__PURE__*/(
            React.createElement("button", { className: `btn btn--${type}`, title: title, onClick: handleClick }, /*#__PURE__*/
                    React.createElement("svg", { className: "icon", viewBox: "0 0 24 24" }, /*#__PURE__*/
                            React.createElement("path", { d: "M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z" }))));



  };


  // =========================
  // Slider
  // =========================

  class Slider extends React.Component {
    constructor(props) {
      super(props);

      this.state = { current: 0 };
      this.handlePreviousClick = this.handlePreviousClick.bind(this);
      this.handleNextClick = this.handleNextClick.bind(this);
      this.handleSlideClick = this.handleSlideClick.bind(this);
    }

    handlePreviousClick() {
      const previous = this.state.current - 1;

      this.setState({
        current: previous < 0 ?
                this.props.slides.length - 1 :
                previous });

    }

    handleNextClick() {
      const next = this.state.current + 1;

      this.setState({
        current: next === this.props.slides.length ?
                0 :
                next });

    }

    handleSlideClick(index) {
      if (this.state.current !== index) {
        this.setState({
          current: index });

      }
    }

    render() {
      const { current, direction } = this.state;
      const { slides, heading } = this.props;
      const headingId = `slider-heading__${heading.replace(/\s+/g, '-').toLowerCase()}`;
      const wrapperTransform = {
        'transform': `translateX(-${current * (100 / slides.length)}%)` };


      return /*#__PURE__*/(
              React.createElement("div", { className: "slider", "aria-labelledby": headingId }, /*#__PURE__*/
                      React.createElement("ul", { className: "slider__wrapper", style: wrapperTransform }, /*#__PURE__*/
                              React.createElement("h3", { id: headingId, class: "visuallyhidden" }, heading),

                              slides.map(slide => {
                                return /*#__PURE__*/(
                                        React.createElement(Slide, {
                                          key: slide.index,
                                          slide: slide,
                                          current: current,
                                          handleSlideClick: this.handleSlideClick }));


                              })), /*#__PURE__*/


                      React.createElement("div", { className: "slider__controls" }, /*#__PURE__*/
                              React.createElement(SliderControl, {
                                type: "previous",
                                title: "Go to previous slide",
                                handleClick: this.handlePreviousClick }), /*#__PURE__*/


                              React.createElement(SliderControl, {
                                type: "next",
                                title: "Go to next slide",
                                handleClick: this.handleNextClick }))));




    }}



  ReactDOM.render( /*#__PURE__*/React.createElement(Slider, { heading: "Example Slider", slides: slideData }), document.getElementById('app'));
  //# sourceURL=pen.js
</script>



</body>

</html>
 
